import requests
from .struct import Format
from bs4 import BeautifulSoup as Soup
import json

class Fetcher(object):
    def __init__(self, pkg_type : str):
        self.pkg_type = pkg_type
        self.pkg2url = {
            Format.pypi : self. __pypi_target_releases,
            Format.npm : self.__npm_target_releases,
            Format.conda : self.__conda_target_releases,
            Format.golang : self.__golang_target_releases,
            Format.maven : self.__maven_target_releases
        }
        self.client = requests.Session()
        self.client.headers.update({'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36'})

    def get_package_releases(self, pkg_info):
        return self.pkg2url[self.pkg_type](pkg_info)

    def __maven_target_releases(self, pkg_info):
        group_id, artifact_id, version = pkg_info[0], pkg_info[1], pkg_info[2]
        maven_central = "https://repo1.maven.org/maven2"
        nexus_host = "http://mirrors.gitee.com/repository/maven-central"
        path = f"{group_id.replace('.', '/')}/{artifact_id}/{version}/"
        target_url = f"{maven_central}/{path}"
        links = map(lambda a:a['href'],Soup(self.client.get(target_url).text, 'html.parser').find_all('a'))
        build_url = lambda path: f"{target_url}{path}".replace(maven_central, nexus_host)
        return [ build_url(i) for i  in links if (not i.endswith('/')) and (not i.startswith('..')) ]

    def __pypi_target_releases(self, pkg_info):
        name, version = pkg_info[0], pkg_info[1]
        pypi_org = "https://pypi.org/simple"
        nexus_host = "http://mirrors.gitee.com/repository/pypi-public"
        target_url = f"{pypi_org}/{name}"
        filenames = list(map(lambda a:a.text, Soup(self.client.get(target_url).text, 'html.parser').find_all('a')))
        build_url = lambda filename : f"{nexus_host}/packages/{name}/{version}/{filename}"
        return [ build_url(filename) for filename in filenames if version in filename]

    def __conda_target_releases(self, pkg_info):
        return []

    def __golang_target_releases(self, pkg_info):
        path, version = pkg_info[0], pkg_info[1]
        exts = ['zip', 'info', 'mod']
        nexus_host = "http://mirrors.gitee.com/repository/go-public"
        try:
            latest = json.loads(self.client.get(f"{nexus_host}/{path}/@latest").text).get("Version")
        except:
            latest = ""
        vlist = self.client.get(f"{nexus_host}/{path}/@v/list").text.split('\n')
        vlist.append(latest)
        result = []
        for version in vlist:
            if version.strip() != "":
                for ext in exts:
                    result.append(f"{nexus_host}/{path}/@v/{version}.{ext}")
        return result

    def __npm_target_releases(self, pkg_info):
        name, version = pkg_info[0], pkg_info[1]
        nexus_host = "http://mirrors.gitee.com/repository/npm-public"
        build_url = lambda : f"{nexus_host}/{name}/-/{name.split('/')[-1]}-{version}.tgz"
        return [build_url()]
